//
//  trace.cpp
//
//  Created by wujialin on 11/3/14.
//  Copyright (c) 2014 wujialin. All rights reserved.
//

#include "trace.h"
#include "include.h"
#include "functions.h"
int cu = 0;
void trace::SetLimitInfo(){
    this->trace_ = true;
    limitInfo.tl_ = 100; //seconds
    limitInfo.vml_ = 100000;//kbs
    limitInfo.ml_ = 10000;//kbs for code text size;
    limitInfo.sl_ = 1000;//kbs;
    limitInfo.fsl_= 1000;//kbs;
}
int trace::getTime(){
	return this->timeUsed_;
}
int trace::GetMemory(){
	return this->memoryUsed_;
}
bool trace::CreateProcess(){
    int pid = fork();
    if (pid < 0) {
        return false;
    }
    else if( pid > 0){
        this->pid_ = pid;
        return true;
    }
    else{
        //set limit for child
        if (this->limitInfo.tl_ > 0) {
            if (SetrLimit(RLIMIT_CPU, this->limitInfo.tl_) == -1) {
                raise(SIGKILL);
            }
        }
        if (this->limitInfo.vml_ > 0) {
            if (SetrLimit(RLIMIT_AS, this->limitInfo.vml_ * 1024) == -1) {
                raise(SIGKILL);
            }
        }
        
        if (this->limitInfo.ml_ > 0) {
            if (SetrLimit(RLIMIT_DATA, this->limitInfo.ml_ * 1024) == -1) {
                raise(SIGKILL);
            }
        }
        if (this->trace_) {
		if(ptrace(PTRACE_TRACEME,0,0,0) == -1){
                raise(SIGKILL);
            }
        }
        //end setting
        //execl("/bin/ls","ls",NULL);
        execl("./app","app",NULL);
	 //execl("/home/jialin/myTest/traceClass/app","app","",(char *)0); 
        printf("executation for app faild\n");
        raise(SIGKILL);
        return false;
    }
}

void trace::updateUsage(){
    int gtime = ReadTimeConsumption(this->pid_);
    int gmemory = ReadMemoryConsumption(this->pid_);
    if (gtime > this->timeUsed_) {
        this->timeUsed_ = gtime;
    }
    if (gmemory > this->memoryUsed_) {
        this->memoryUsed_ = gmemory;
    }
}
void trace::waitForChild(){
    if (!this->CreateProcess() ) {
        printf("create process faild\n");
        raise(SIGKILL);
    }
    printf("child pid:%d\n",this->pid_ );
    int status;int sig;
    while (waitpid(this->pid_,&status,0)) {
        if (!WIFSTOPPED(status)) {
            this->result_ = 0;
            printf(" child exited\n");
            break;
        }
        sig = WSTOPSIG(status);
	struct user_regs_struct regs;
	cu++;
       //this->updateUsage();
        if (sig == SIGTRAP) {
		
		printf("count:%d\n", cu);
	     //ptrace(PTRACE_GETREGS, pid_, 0, &regs);		
            ptrace(PTRACE_SYSCALL,this->pid_,0,0);
            this->updateUsage();

        }
        else{
		printf("else count:%d\n", cu);
            ptrace(PTRACE_SYSCALL,this->pid_,0,sig);
	//	ptrace(PTRACE_SYSCALL,pid_,0,0);
	   this->updateUsage();
            //sysCall handle
            //continue;
        }
        
    }
}
